package com.zenithmind.mall.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zenithmind.common.exception.BusinessException;
import com.zenithmind.mall.mapper.ProductStockMapper;
import com.zenithmind.mall.pojo.entity.ProductStock;
import com.zenithmind.mall.service.ProductStockService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 商品库存服务实现类 - 遵循单一职责原则，专门负责商品库存相关操作
 * 
 * @author ZenithMind Team
 * @since 2025-07-03
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ProductStockServiceImpl implements ProductStockService {

    private final ProductStockMapper productStockMapper;

    @Override
    public Boolean checkStock(String productId, Integer quantity) {
        LambdaQueryWrapper<ProductStock> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ProductStock::getProductId, productId);
        ProductStock stock = productStockMapper.selectOne(wrapper);
        if (stock == null) {
            return false;
        }
        return stock.hasEnoughStock(quantity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean decreaseStock(String productId, Integer quantity) {
        if (quantity == null || quantity <= 0) {
            throw new BusinessException("扣减数量必须大于0");
        }

        LambdaQueryWrapper<ProductStock> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ProductStock::getProductId, productId);
        ProductStock stock = productStockMapper.selectOne(wrapper);
        if (stock == null) {
            throw new BusinessException("商品库存不存在");
        }

        if (!stock.decreaseStock(quantity)) {
            throw new BusinessException("库存不足");
        }

        // 使用乐观锁更新
        int result = productStockMapper.updateById(stock);
        if (result <= 0) {
            throw new BusinessException("库存更新失败，请重试");
        }

        log.info("扣减库存成功: productId={}, quantity={}, remainingStock={}",
                productId, quantity, stock.getAvailableStock());
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean increaseStock(String productId, Integer quantity) {
        if (quantity == null || quantity <= 0) {
            throw new BusinessException("增加数量必须大于0");
        }

        LambdaQueryWrapper<ProductStock> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ProductStock::getProductId, productId);
        ProductStock stock = productStockMapper.selectOne(wrapper);
        if (stock == null) {
            throw new BusinessException("商品库存不存在");
        }

        stock.increaseStock(quantity);

        int result = productStockMapper.updateById(stock);
        if (result <= 0) {
            throw new BusinessException("库存更新失败");
        }

        log.info("增加库存成功: productId={}, quantity={}, currentStock={}",
                productId, quantity, stock.getStock());
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean lockStock(String id, Integer quantity) {
        if (quantity == null || quantity <= 0) {
            throw new BusinessException("锁定数量必须大于0");
        }
        
        ProductStock stock = productStockMapper.selectById(id);
        if (stock == null) {
            throw new BusinessException("商品库存不存在");
        }
        
        if (!stock.lockStock(quantity)) {
            throw new BusinessException("可用库存不足，无法锁定");
        }
        
        // 使用乐观锁更新
        int result = productStockMapper.updateById(stock);
        if (result <= 0) {
            throw new BusinessException("锁定库存失败，请重试");
        }
        
        log.info("锁定库存成功: productId={}, quantity={}, lockedStock={}", 
                id, quantity, stock.getLockedStock());
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean unlockStock(String id, Integer quantity) {
        if (quantity == null || quantity <= 0) {
            throw new BusinessException("释放数量必须大于0");
        }
        
        ProductStock stock = productStockMapper.selectById(id);
        if (stock == null) {
            throw new BusinessException("商品库存不存在");
        }
        
        stock.unlockStock(quantity);
        
        int result = productStockMapper.updateById(stock);
        if (result <= 0) {
            throw new BusinessException("释放库存失败");
        }
        
        log.info("释放库存成功: productId={}, quantity={}, lockedStock={}", 
                id, quantity, stock.getLockedStock());
        return true;
    }

    @Override
    public Map<String, Boolean> batchCheckStock(Map<String, Integer> stockRequests) {
        Map<String, Boolean> results = new HashMap<>();
        
        for (Map.Entry<String, Integer> entry : stockRequests.entrySet()) {
            String productId = entry.getKey();
            Integer quantity = entry.getValue();
            
            try {
                Boolean result = checkStock(productId, quantity);
                results.put(productId, result);
            } catch (Exception e) {
                log.error("检查库存失败: productId={}", productId, e);
                results.put(productId, false);
            }
        }
        
        return results;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchDecreaseStock(Map<String, Integer> stockChanges) {
        for (Map.Entry<String, Integer> entry : stockChanges.entrySet()) {
            String productId = entry.getKey();
            Integer quantity = entry.getValue();
            
            if (!decreaseStock(productId, quantity)) {
                throw new BusinessException("批量扣减库存失败: " + productId);
            }
        }
        
        log.info("批量扣减库存成功: {}", stockChanges);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchIncreaseStock(Map<String, Integer> stockChanges) {
        for (Map.Entry<String, Integer> entry : stockChanges.entrySet()) {
            String productId = entry.getKey();
            Integer quantity = entry.getValue();
            
            if (!increaseStock(productId, quantity)) {
                throw new BusinessException("批量增加库存失败: " + productId);
            }
        }
        
        log.info("批量增加库存成功: {}", stockChanges);
        return true;
    }

    @Override
    public Integer getCurrentStock(String productId) {
        LambdaQueryWrapper<ProductStock> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ProductStock::getProductId, productId);
        ProductStock stock = productStockMapper.selectOne(wrapper);
        return stock != null ? stock.getStock() : 0;
    }

    @Override
    public Integer getAvailableStock(String productId) {
        LambdaQueryWrapper<ProductStock> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ProductStock::getProductId, productId);
        ProductStock stock = productStockMapper.selectOne(wrapper);
        return stock != null ? stock.getAvailableStock() : 0;
    }

    @Override
    public Integer getLockedStock(String productId) {
        LambdaQueryWrapper<ProductStock> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ProductStock::getProductId, productId);
        ProductStock stock = productStockMapper.selectOne(wrapper);
        return stock != null ? stock.getLockedStock() : 0;
    }

    @Override
    public List<String> getLowStockProducts() {
        LambdaQueryWrapper<ProductStock> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ProductStock::getIsDeleted, 0)
               .apply("stock <= low_stock AND low_stock > 0");
        
        List<ProductStock> lowStockList = productStockMapper.selectList(wrapper);
        
        return lowStockList.stream()
                .map(ProductStock::getProductId)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean setStockThreshold(String id, Integer threshold) {
        ProductStock stock = productStockMapper.selectById(id);
        if (stock == null) {
            throw new BusinessException("商品库存不存在");
        }
        
        stock.setLowStock(threshold);
        
        int result = productStockMapper.updateById(stock);
        if (result <= 0) {
            throw new BusinessException("设置库存预警阈值失败");
        }
        
        log.info("设置库存预警阈值成功: productId={}, threshold={}", id, threshold);
        return true;
    }
}
